package com.pactera.asmp.server.schedule;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.apache.commons.collections.MapUtils;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.pactera.asmp.server.common.constants.ScreenRedisKey;
import com.pactera.asmp.server.dao.ScriptInfoMapper;
import com.pactera.asmp.server.dao.UserProjectMapper;
import com.pactera.asmp.server.entity.ScriptStatisticsDataDTO;
import com.pactera.asmp.server.entity.UserProjectStatisticsDataDTO;

@Service
@EnableScheduling
public class ScriptSchedule {

    private Logger logger = LoggerFactory.getLogger(ScriptSchedule.class);

    @Autowired
    private ScriptInfoMapper scriptInfoMapper;

    @Autowired
    private UserProjectMapper userProjectMapper;

    @Autowired
    private StringRedisTemplate redisTemplate;

    /**
     * 统计项目创建时长的数据（每天执行一次）
     */
    @Scheduled(cron = "0 1 0 * * ?")
    public void calculateScriptTime(){
        logger.info("============ calculate script start ============");
        List<ScriptStatisticsDataDTO> dataList = scriptInfoMapper.summaryScriptInfoByProject();
        if(CollectionUtils.isEmpty(dataList)) {
            logger.info("no data");
            logger.info("============ calculate script end ============");
            return;
        }
        // 获取项目中测试人员数量
        List<UserProjectStatisticsDataDTO> userProjectList = userProjectMapper.summaryTestUserByProjectId();
        Map<Integer, Long> userProjectMap = userProjectList.stream().collect(Collectors.toMap(UserProjectStatisticsDataDTO::getProjectId, UserProjectStatisticsDataDTO::getUserCount));
        Map<Integer, List<ScriptStatisticsDataDTO>> mapByProjectId = dataList.stream().collect(Collectors.groupingBy(ScriptStatisticsDataDTO::getProjectId));
        for(Integer projectId : mapByProjectId.keySet()) {
            // 脚本类型分布
            List<ScriptStatisticsDataDTO> scriptCategoryList = Lists.newArrayList();
            Map<String, List<ScriptStatisticsDataDTO>> mapByScriptCategory = mapByProjectId.get(projectId).stream().collect(Collectors.groupingBy(ScriptStatisticsDataDTO::getScriptCategory));
            for(String scriptCategory : mapByScriptCategory.keySet()) {
                ScriptStatisticsDataDTO scriptStatisticsDataDTO = new ScriptStatisticsDataDTO();
                scriptStatisticsDataDTO.setProjectId(projectId);
                scriptStatisticsDataDTO.setScriptCategory(scriptCategory);
                scriptStatisticsDataDTO.setScriptNum(mapByScriptCategory.get(scriptCategory).stream().mapToLong(ScriptStatisticsDataDTO::getScriptNum).sum());
                scriptCategoryList.add(scriptStatisticsDataDTO);
            }
            redisTemplate.opsForHash().put(ScreenRedisKey.REDIS_KEY_SCREEN_SCRIPT_BY_CATEGORY, projectId.toString(), JSONObject.toJSONString(scriptCategoryList));

            // 按照人员编写分布
            List<ScriptStatisticsDataDTO> userList = Lists.newArrayList();
            Map<Integer, List<ScriptStatisticsDataDTO>> mapByUser = mapByProjectId.get(projectId).stream().collect(Collectors.groupingBy(ScriptStatisticsDataDTO::getUserId));
            for(Integer userId : mapByUser.keySet()) {
                ScriptStatisticsDataDTO scriptStatisticsDataDTO = new ScriptStatisticsDataDTO();
                scriptStatisticsDataDTO.setProjectId(projectId);
                scriptStatisticsDataDTO.setUserId(userId);
                scriptStatisticsDataDTO.setUsername(mapByUser.get(userId).get(0).getUsername());
                scriptStatisticsDataDTO.setScriptNum(mapByUser.get(userId).stream().mapToLong(ScriptStatisticsDataDTO::getScriptNum).sum());
                userList.add(scriptStatisticsDataDTO);
            }
            redisTemplate.opsForHash().put(ScreenRedisKey.REDIS_KEY_SCREEN_SCRIPT_BY_USER, projectId.toString(), JSONObject.toJSONString(userList));

            if(MapUtils.isNotEmpty(userProjectMap)) {
                BigDecimal rate = new BigDecimal(userProjectMap.getOrDefault(projectId, 0L))
                        .divide(new BigDecimal(mapByProjectId.get(projectId).stream().mapToLong(ScriptStatisticsDataDTO::getScriptNum).sum()), 4, BigDecimal.ROUND_HALF_UP);
                redisTemplate.opsForHash().put(ScreenRedisKey.REDIS_KEY_SCREEN_PERSON_INVESTMENT_RATE, projectId.toString(), rate.toString());
            }
        }
        logger.info("============ calculate script end ============");
    }
}
